#ifndef RTE_KB9115_NSTREAM_H
#define RTE_KB9115_NSTREAM_H

#include "logger_rte.h"

using u8 = unsigned char;
using uint32_t = uint32_t;
#define TX_INV 0x1
#define RX_INV 0x2
#define TX_RX_SWAP 0x4
#define IS_OPEN 0x8
#define FLAG_FORWARD 0x10
#define FLAG_SYSEX 0x20
#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2

class nStream {
public:
    nStream() = default;

    virtual void begin(uint8_t address, bool generalCall = false);

    int write(const char *str) {
        if (str == NULL) {
            return 0;
        }
        return write((const uint8_t *) str, strlen(str));
    }

#ifdef ARDUINO

    int print(const __FlashStringHelper *);

    int print(const String &);

    int print(const Printable &);

    int println(const __FlashStringHelper *);

    int println(const String &s);

    int println(const Printable &);

    int printf(const __FlashStringHelper *format, ...);
#endif

    int print(const char []);

    int print(char);

    int print(unsigned char, int = DEC);

    int print(int, int = DEC);

    int print(unsigned int, int = DEC);

    int print(long, int = DEC);

    int print(unsigned long, int = DEC);

    int print(long long, int = DEC);

    int print(unsigned long long, int = DEC);

    int print(double, int = 2);


    int println(const char []);

    int println(char);

    int println(unsigned char, int = DEC);

    int println(int, int = DEC);

    int println(unsigned int, int = DEC);

    int println(long, int = DEC);

    int println(unsigned long, int = DEC);

    int println(long long, int = DEC);

    int println(unsigned long long, int = DEC);

    int println(double, int = 2);


    int println(void);

    int printf(const char *format, ...);


    virtual int tx_max_size();

    u8 flag{};

    void forward(uint8_t c);

    void closeForward();

    virtual void beginTransmission(uint8_t) {
        logger.error("nStream::beginTransmission() not implemented");
    }

    virtual u8 endTransmission(u8 sendStop);

    virtual u8 endTransmission();

    virtual int available_wait(int Delay) = 0;

    virtual int availableForWrite();

    virtual int read_wait(int timeout = -1) = 0;

    virtual int write(uint8_t c) = 0;

    virtual int write(const u8 *buffer, int size);

    virtual uint8_t requestFrom(int address, int quantity) {
        return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) true);
    }

    virtual uint8_t requestFrom(int address, int quantity, int sendStop) {
        return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) sendStop);
    }

    virtual int available();

    virtual int read();

    virtual int peek();

    virtual void flush();

    int printNumber(unsigned long, uint8_t);

    int printULLNumber(unsigned long long, uint8_t);

    int printFloat(double, uint8_t);

    int readBytes(char *buffer, int length) {
        int count = 0;
        while (count < length) {
            int c = read();
            if (c < 0) {
                break;
            }
            *buffer++ = (char) c;
            count++;
        }
        return count;
    }

    nStream *forwardStream = nullptr;
    uint32_t tick_forward{};
    void *tx_lock = nullptr;
};

#endif // RTE_KB9115_NSTREAM_H
